package com.ym.wcp.framework.advice;

import com.ym.wcp.framework.response.R;
import com.ym.wcp.framework.security.ApiResultDesSecurity;
import com.ym.wcp.framework.security.ApiResultSecurity;
import com.ym.wcp.framework.security.ApiResultSm4Security;
import com.ym.wcp.framework.security.IApiResultSecurity;
import com.ym.wcp.framework.utils.DesUtil;
import com.ym.wcp.framework.utils.JsonUtil;
import com.ym.wcp.framework.utils.SM4Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;
import java.net.URI;
import java.util.Objects;

@ControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice {

    @Autowired
    private ApplicationContext ctx;


    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest request, ServerHttpResponse serverHttpResponse) {
        Method method = methodParameter.getMethod();
        ApiResultSecurity ann = method.getAnnotation(ApiResultSecurity.class);
        if (ann != null && ann.securityClass() != null) {
            IApiResultSecurity bean = ctx.getBean(ann.securityClass());
            if (Objects.equals(ann.securityClass(), ApiResultSm4Security.class) &&
                    bean != null &&
                    !StringUtils.isEmpty(bean.getKey()) &&
                    bean.getKey().length() == 16) {
                if (o instanceof R) {
                    R r = (R) o;
                    Object data = r.getData();
                    if (data != null) {
                        String securityText = "";
                        if (data.getClass() == String.class) {
                            securityText = SM4Utils.encryptData_ECB((String) data, bean.getKey());
                        } else {
                            securityText = SM4Utils.encryptData_ECB(JsonUtil.objectToJson(data), bean.getKey());
                        }
                        r.setData(securityText);
                    } else {
                        r.setData("");
                    }
                }
            } else if (Objects.equals(ann.securityClass(), ApiResultDesSecurity.class) &&
                    bean != null &&
                    !StringUtils.isEmpty(bean.getKey())) {
                if (o instanceof R) {
                    R r = (R) o;
                    Object data = r.getData();
                    if (data != null) {
                        String securityText = "";
                        if (data.getClass() == String.class) {
                            securityText = DesUtil.encrypt((String) data, bean.getKey());
                        } else {
                            securityText = DesUtil.encrypt(JsonUtil.objectToJson(data), bean.getKey());
                        }
                        r.setData(securityText);
                    } else {
                        r.setData("");
                    }
                }
            }
        }

        if (o instanceof R) {
            R r = (R) o;
            URI uri = request.getURI();
            if (uri != null) {
                r.setPath(uri.getPath() == null ? uri.getRawPath() : uri.getPath());
            }
            return r;
        }
        return o;
    }
}
